﻿@page "/system/audittrails"
@using CleanArchitecture.Blazor.Application.Features.AuditTrails.DTOs
@using CleanArchitecture.Blazor.Application.Features.AuditTrails.Queries.PaginationQuery
@using CleanArchitecture.Blazor.Application.Features.AuditTrails.Specifications
@using CleanArchitecture.Blazor.Application.Features.AuditTrails.Caching
@using CleanArchitecture.Blazor.Server.UI.Components.UtcToLocalTime
@using CleanArchitecture.Blazor.Server.UI.Services.JsInterop

@attribute [Authorize(Policy = Permissions.AuditTrails.View)]
@inject IStringLocalizer<AuditTrails> L
<PageTitle>@Title</PageTitle>

<MudDataGrid ServerData="@(ServerReload)"
             T="AuditTrailDto"
             FixedHeader="true"
             FixedFooter="false"
             @bind-RowsPerPage="_defaultPageSize"
             Loading="@_loading"
             Hover="true" @ref="_auditTrailGrid">
    <ToolBarContent>
        <MudStack Row Spacing="0" Class="flex-grow-1" Justify="Justify.SpaceBetween">
            <!-- Left Toolbar: Icon, Title and List View -->
            <MudStack Row AlignItems="AlignItems.Start">
                <MudIcon Icon="@Icons.Material.Filled.ReceiptLong" Size="Size.Large" />
                <MudStack Spacing="0">
                    <MudText Typo="Typo.subtitle2" Class="mb-2">@Title</MudText>
                    <MudEnumSelect Style="min-width:120px"
                                   TEnum="AuditTrailListView"
                                   ValueChanged="OnListViewChanged"
                                   Value="_auditTrailsQuery.ListView"
                                   Dense="true"
                                   Label="@L["List View"]">
                    </MudEnumSelect>
                </MudStack>
            </MudStack>
            <!-- Right Toolbar: Actions and Search -->
            <MudStack Spacing="0" AlignItems="AlignItems.End">
                <MudToolBar Dense WrapContent="true" Class="py-1 px-0">
                    <MudButton OnClick="OnRefreshAuditTrails"
                               StartIcon="@Icons.Material.Outlined.Refresh">
                        @ConstantString.Refresh
                    </MudButton>
                </MudToolBar>
                <MudStack Row Spacing="1" AlignItems="AlignItems.End">
                    <!-- Search by audit type -->
                    <MudEnumSelect TEnum="AuditType ?"
                                   Placeholder="@L["Search by audit type"]"
                                   Value="_auditTrailsQuery.AuditType"
                                   Clearable="true"
                                   ValueChanged="OnAuditTypeSearch"
                                   Style="min-width:120px"
                                   FullWidth="true">
                    </MudEnumSelect>
                    <!-- Keyword search (hidden on small screens) -->
                    <MudHidden Breakpoint="Breakpoint.SmAndDown">
                        <MudTextField T="string"
                                      Value="_auditTrailsQuery.Keyword"
                                      ValueChanged="OnKeywordSearch"
                                      Placeholder="Search"
                                      Adornment="Adornment.End"
                                      Style="min-width:120px"
                                      FullWidth="true"
                                      AdornmentIcon="@Icons.Material.Filled.Search"
                                      IconSize="Size.Small">
                        </MudTextField>
                    </MudHidden>
                </MudStack>
            </MudStack>
        </MudStack>
    </ToolBarContent>
    <Columns>
        <HierarchyColumn T="AuditTrailDto" ButtonDisabledFunc="@(x => x.AuditType == AuditType.None)" />
        <PropertyColumn Property="x => x.UserId" Title="@L[_currentDto.GetMemberDescription(x => x.UserId)]">
            <CellTemplate>
                <div class="d-flex flex-column">
                    <MudText Typo="Typo.body2">@context.Item.Owner?.UserName</MudText>
                    <MudText Typo="Typo.body2" Class="mud-text-secondary">@context.Item.UserId</MudText>
                </div>
            </CellTemplate>
        </PropertyColumn>
        <PropertyColumn Property="x => x.AuditType" Title="@L[_currentDto.GetMemberDescription(x => x.AuditType)]" />
        <PropertyColumn Property="x => x.TableName" Title="@L[_currentDto.GetMemberDescription(x => x.TableName)]" />
        <PropertyColumn Property="x => x.PrimaryKey" Title="@L[_currentDto.GetMemberDescription(x => x.PrimaryKey)]" />
        <PropertyColumn Property="x => x.DateTime" Title="@L[_currentDto.GetMemberDescription(x => x.DateTime)]">
            <CellTemplate>
                <UtcToLocal UTCDateTime="@context.Item.DateTime"></UtcToLocal>
            </CellTemplate>
        </PropertyColumn>
    </Columns>
    <ChildRowContent>
        <MudCard Elevation="0" Class="d-flex flex-grow-0">
            <MudCardHeader>
                <CardHeaderContent>
                    <MudText Typo="Typo.body1">
                        <strong>@L[context.Item.TableName!]</strong>
                    </MudText>
                </CardHeaderContent>
            </MudCardHeader>
            <MudCardContent Class="py-3">
                <MudExpansionPanels Dense Class="mt-2" Elevation="0" MultiExpansion>
                    <MudExpansionPanel Dense Gutters>
                        <TitleContent>
                            <MudStack Row AlignItems="AlignItems.Center" Spacing="2">
                                @if (context.Item.IsSuccessful)
                                {
                                    <MudIcon Size="Size.Small" Icon="@Icons.Material.Filled.CheckCircle" Color="Color.Success"></MudIcon>
                                }
                                else
                                {
                                    <MudIcon Size="Size.Small" Icon="@Icons.Material.Filled.ErrorOutline" Color="Color.Error"></MudIcon>
                                }
                                <MudText>@L["History data"]</MudText>
                            </MudStack>
                        </TitleContent>
                        <ChildContent>
                            <MudSimpleTable Hover="true" Dense Elevation="0" Bordered="false">
                                <thead>
                                    <tr>
                                        <th>@L["Field Name"]</th>
                                        <th>@L[_currentDto.GetMemberDescription(x => x.OldValues)]</th>
                                        <th>@L[_currentDto.GetMemberDescription(x => x.NewValues)]</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    @foreach (var field in (context.Item.NewValues?.Any() ?? false
                                                                        ? context.Item.NewValues
                                                                        : context.Item.OldValues?.Any() ?? false
                                                                        ? context.Item.OldValues
                                                                        : new Dictionary<string, object?>()))
                                    {
                                        <tr>
                                            <td>@field.Key</td>
                                            <td class="mud-text-secondary">@(context.Item.OldValues?.ContainsKey(field.Key) ?? false ? context.Item.OldValues[field.Key] : string.Empty)</td>
                                            <td>@(context.Item.NewValues?.ContainsKey(field.Key) ?? false ? context.Item.NewValues[field.Key] : string.Empty)</td>
                                        </tr>
                                    }
                                </tbody>
                            </MudSimpleTable>
                        </ChildContent>
                    </MudExpansionPanel>
                    @if (context.Item.IsSuccessful == false)
                    {
                        <MudExpansionPanel Text="@L[_currentDto.GetMemberDescription(x => x.ErrorMessage)]" Dense Gutters>
                            <MudText Typo="Typo.body2">@context.Item.ErrorMessage</MudText>
                        </MudExpansionPanel>
                    }
                    <MudExpansionPanel Text="@L[_currentDto.GetMemberDescription(x => x.DebugView)]" Dense Gutters>
                        <MudText Typo="Typo.body2">@context.Item.DebugView</MudText>
                    </MudExpansionPanel>
                </MudExpansionPanels>
            </MudCardContent>
        </MudCard>
    </ChildRowContent>
    <NoRecordsContent>
        <MudText>@ConstantString.NoRecords</MudText>
    </NoRecordsContent>
    <LoadingContent>
        <MudText>@ConstantString.Loading</MudText>
    </LoadingContent>
    <PagerContent>
        <MudDataGridPager PageSizeOptions="@(new[] { 10, 15, 30, 50, 100, 500, 1000 })" />
    </PagerContent>
</MudDataGrid>

@code {
    // Public page title
    public string Title { get; private set; } = "Audit Trails";

    // Private fields using underscore and camelCase naming
    private MudDataGrid<AuditTrailDto> _auditTrailGrid = null!;
    private bool _loading;
    private int _defaultPageSize = 15;
    private readonly AuditTrailDto _currentDto = new();

    // _auditTrailsQuery parameters for pagination; using PascalCase for public properties and _camelCase for private fields
    private AuditTrailsWithPaginationQuery _auditTrailsQuery { get; } = new();

    [CascadingParameter] private UserProfile? UserProfile { get; set; }
    private AuditTrailsAccessRights _accessRights = new();

    protected override async Task OnInitializedAsync()
    {
        // Set page title based on current DTO's class description
        Title = L[_currentDto.GetClassDescription()];
        _accessRights = await PermissionService.GetAccessRightsAsync<AuditTrailsAccessRights>();
    }

    // Server data loading callback for the grid
    private async Task<GridData<AuditTrailDto>> ServerReload(GridState<AuditTrailDto> state)
    {
        try
        {
            _loading = true;
            _auditTrailsQuery.CurrentUser = UserProfile;
            _auditTrailsQuery.OrderBy = state.SortDefinitions.FirstOrDefault()?.SortBy ?? "Id";
            _auditTrailsQuery.SortDirection = (state.SortDefinitions.FirstOrDefault()?.Descending ?? true)
                                  ? SortDirection.Descending.ToString()
                                  : SortDirection.Ascending.ToString();
            _auditTrailsQuery.PageNumber = state.Page + 1;
            _auditTrailsQuery.PageSize = state.PageSize;
            var result = await Mediator.Send(_auditTrailsQuery).ConfigureAwait(false);
            return new GridData<AuditTrailDto> { TotalItems = result.TotalItems, Items = result.Items };
        }
        finally
        {
            _loading = false;
        }
    }

    // Event handler for when the list view is changed
    private async Task OnListViewChanged(AuditTrailListView listview)
    {
        _auditTrailsQuery.ListView = listview;
        await _auditTrailGrid.ReloadServerData();
    }

    // Event handler for keyword search
    private async Task OnKeywordSearch(string text)
    {
        _auditTrailsQuery.Keyword = text;
        await _auditTrailGrid.ReloadServerData();
    }

    // Event handler for audit type search
    private async Task OnAuditTypeSearch(AuditType? auditType)
    {
        _auditTrailsQuery.AuditType = auditType;
        await _auditTrailGrid.ReloadServerData();
    }

    // Refresh callback
    private async Task OnRefreshAuditTrails()
    {
        AuditTrailsCacheKey.Refresh();
        _auditTrailsQuery.Keyword = string.Empty;
        await _auditTrailGrid.ReloadServerData();
    }

    // Toggle detail view for a specific audit trail
    private Task OnToggleDetail(AuditTrailDto dto)
    {
        dto.ShowDetails = !dto.ShowDetails;
        return Task.CompletedTask;
    }
}
